package cn.zhangfusheng.elasticsearch.factory.proxy;

import cn.zhangfusheng.elasticsearch.mybatis.ElasticSearchWithMybatisXmlConfig;
import cn.zhangfusheng.elasticsearch.repository.ElasticSearchRepository;
import cn.zhangfusheng.elasticsearch.scan.ElasticSearchEntityRepositoryDetail;
import cn.zhangfusheng.elasticsearch.template.ElasticSearchRestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * cglib 代理
 * @author fusheng.zhang
 * @date 2022-04-29 17:20:58
 */
@Slf4j
public class RepositoryCglibProxy<T extends ElasticSearchRepository<?>> extends RepositoryProxy<T> implements MethodInterceptor {

    private final ElasticSearchRepository<?> defaultElasticSearchRepository;
    private final Object object;

    public RepositoryCglibProxy(
            ElasticSearchRepository<?> defaultElasticSearchRepository,
            ElasticSearchEntityRepositoryDetail entityRepositoryDetail,
            ElasticSearchRestTemplate elasticSearchRestTemplate,
            ElasticSearchWithMybatisXmlConfig elasticSearchWithMybatisXmlConfig) {
        super(entityRepositoryDetail, elasticSearchRestTemplate, elasticSearchWithMybatisXmlConfig);
        this.defaultElasticSearchRepository = defaultElasticSearchRepository;
        this.object = Enhancer.create(entityRepositoryDetail.getElasticSearchRepositoryClass(), this);
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if (method.getDeclaringClass() == Object.class) return method.invoke(this, objects);
        if (super.isDefaultMethod(method)) return method.invoke(defaultElasticSearchRepository, objects);
        return super.getResult(method, objects);
    }

    @SuppressWarnings("unchecked")
    @Override
    public T getObject() {
        return (T) this.object;
    }
}
